package org.lc.stk.service.baseInfo.impl;

import java.util.List;
import java.util.Optional;

import org.lc.stk.dao.baseInfo.MajorRepository;
import org.lc.stk.model.baseInfo.Major;
import org.lc.stk.service.baseInfo.MajorService;
import org.lc.stk.service.exception.BusinessException;
import org.lc.stk.service.support.QuerySpecifications;
import org.lc.stk.web.dto.major.CreateMajorRequest;
import org.lc.stk.web.dto.major.MajorQuery;
import org.lc.stk.web.dto.major.UpdateMajorRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
@Transactional(readOnly = true)
public class MajorServiceImpl implements MajorService {

    @Autowired
    private MajorRepository majorRepository;

    @Override
    @Transactional
    public Major create(CreateMajorRequest request) {
        // 检查编码唯一性
        if (isCodeExists(request.getCode(), null)) {
            throw new BusinessException("专业编码已存在");
        }

        // 检查名称唯一性
        if (isNameExists(request.getName(), null)) {
            throw new BusinessException("专业名称已存在");
        }

        Major major = new Major();
        major.setName(request.getName());
        major.setCode(request.getCode());
        major.setEnabled(request.getEnabled());
        major.setOrderNum(request.getOrderNum());
        major.setRemark(request.getRemark());

        return majorRepository.save(major);
    }

    @Override
    @Transactional
    public Major update(UpdateMajorRequest request) {
        Major major = getById(request.getId());

        // 检查编码唯一性
        if (StringUtils.hasText(request.getCode()) 
            && !request.getCode().equals(major.getCode())
            && isCodeExists(request.getCode(), request.getId())) {
            throw new BusinessException("专业编码已存在");
        }

        // 检查名称唯一性
        if (StringUtils.hasText(request.getName()) 
            && !request.getName().equals(major.getName())
            && isNameExists(request.getName(), request.getId())) {
            throw new BusinessException("专业名称已存在");
        }

        if (StringUtils.hasText(request.getName())) {
            major.setName(request.getName());
        }
        if (StringUtils.hasText(request.getCode())) {
            major.setCode(request.getCode());
        }
        if (request.getEnabled() != null) {
            major.setEnabled(request.getEnabled());
        }
        if (request.getOrderNum() != null) {
            major.setOrderNum(request.getOrderNum());
        }
        major.setRemark(request.getRemark());

        return majorRepository.save(major);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        Major major = getById(id);
        major.setIsDeleted(true);
        majorRepository.save(major);
    }

    @Override
    public Major getById(Integer id) {
        return majorRepository.findByIdAndIsDeletedFalse(id)
                .orElseThrow(() -> new BusinessException("专业不存在"));
    }

    @Override
    public List<Major> listEnabled() {
        return majorRepository.findByIsDeletedFalseAndEnabledTrueOrderByOrderNum();
    }

    @Override
    public Page<Major> query(MajorQuery query, Pageable pageable) {
        Specification<Major> spec = buildSpecification(query);
        return majorRepository.findAll(spec, pageable);
    }

    private Specification<Major> buildSpecification(MajorQuery query) {
        Specification<Major> spec = Specification.where(
            QuerySpecifications.equal("isDeleted", false)
        );

        if (StringUtils.hasText(query.getName())) {
            spec = spec.and(QuerySpecifications.like("name", query.getName()));
        }
        if (StringUtils.hasText(query.getCode())) {
            spec = spec.and(QuerySpecifications.like("code", query.getCode()));
        }
        if (query.getEnabled() != null) {
            spec = spec.and(QuerySpecifications.equal("enabled", query.getEnabled()));
        }

        return spec;
    }

    @Override
    public boolean isCodeExists(String code, Integer excludeId) {
        Optional<Major> existing = majorRepository.findByCodeAndIsDeletedFalse(code);
        return existing.isPresent() && !existing.get().getId().equals(excludeId);
    }

    @Override
    public boolean isNameExists(String name, Integer excludeId) {
        Optional<Major> existing = majorRepository.findByNameAndIsDeletedFalse(name);
        return existing.isPresent() && !existing.get().getId().equals(excludeId);
    }

    @Override
    @Transactional
    public void toggleEnabled(List<Integer> ids, boolean enabled) {
        // 验证所有ID都存在且未删除
        ids.forEach(this::getById);
        
        int updated = majorRepository.updateEnabledByIds(ids, enabled);
        if (updated != ids.size()) {
            throw new BusinessException("部分专业更新失败");
        }
    }
}